https://github.com/GeeeekExplorer/NJU-ICS/blob/master/pa2018_fall/nemu/src/monitor/expr.c ># PA0 编译NEMU
- 把项目拉下来,
- 修改学号,姓名
bug:
llvm的TargetRegister.h的位置(/src/utils/distasm.cc), 使用文件搜索locate xxx, 然后修改为查找到的位置- make clean –> make
fatal error: readline/readline.h: No such file or directory
-get install libreadline-dev sudo apt
安装的工具
-get install build-essential # build-essential packages, include binary utilities, gcc, make, and so on
apt-get install man # on-line reference manual
apt-get install gcc-doc # on-line reference manual for gcc
apt-get install gdb # GNU debugger
apt-get install git # revision control system
apt-get install libreadline-dev # a library used later
apt-get install libsdl2-dev # a library used later
apt-get install llvm # llvm project, which contains libraries used later apt
: error: ‘class llvm::MCInstPrinter’ has no member named ‘setPrintBranchImmAsAddress’
修改llvm的版本
-10
sudo apt autoremove llvm-12
sudo apt install llvm/usr/bin
cd -s /usr/lib/llvm-12/bin/llvm-config llvm-config sudo ln
PA1 深入了解代码框架
- 这里的pa是
2020的isa-x86
的pa- 首先是编译项目
- 运行项目
- 哦豁,不出意外是出意外了assert….(问题不大, 只有有报错信息问题就不大)
尝试解决
assert
报错
// 编译
-12-14-ubuntu:~/ics/ics2020/nemu$ make -B
ubuntu@VM
-nemu-interpreter
Building x86+ CC src/device/audio.c
+ CC src/device/io/map.c
+ CC src/device/io/port-io.c
+ CC src/device/io/mmio.c
+ CC src/device/device.c
+ CC src/device/timer.c
+ CC src/device/serial.c
+ CC src/device/intr.c
....
+ LD build/x86-nemu-interpreter
// 运行
-12-14-ubuntu:~/ics/ics2020/nemu$ make run
ubuntu@VM
// 报错
-nemu-interpreter
Building x86-C /home/ubuntu/ics/ics2020/nemu/tools/kvm-diff
make [1]: Entering directory '/home/ubuntu/ics/ics2020/nemu/tools/kvm-diff'
make[1]: Nothing to be done for 'app'.
make[1]: Leaving directory '/home/ubuntu/ics/ics2020/nemu/tools/kvm-diff'
make./build/x86-nemu-interpreter --log=./build/nemu-log.txt --diff=/home/ubuntu/ics/ics2020/nemu/tools/kvm-diff/build/x86-kvm-so
-nemu-interpreter: src/isa/x86/reg.c:20: reg_test: Assertion `reg_w(i) == (sample[i] & 0xffff)' failed.
x86: *** [Makefile:108: run] Aborted (core dumped) make
- 查看
src/isa/x86/reg.c:20:
1 #include <isa.h>
2 #include <stdlib.h>
3 #include <time.h>
4 #include "local-include/reg.h"
5
6 const char *regsl[] = {"eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"};
7 const char *regsw[] = {"ax", "cx", "dx", "bx", "sp", "bp", "si", "di"};
8 const char *regsb[] = {"al", "cl", "dl", "bl", "ah", "ch", "dh", "bh"};
9
10 void reg_test() {
11 srand(time(0));
12 word_t sample[8];
13 word_t pc_sample = rand();
14 cpu.pc = pc_sample;
15
16 int i;
17 for (i = R_EAX; i <= R_EDI; i ++) {
18 sample[i] = rand();
19 reg_l(i) = sample[i];
// 问题出在这里, 可是这几个宏有点折磨了, 盲猜是不是数据越界了
[20] assert(reg_w(i) == (sample[i] & 0xffff));
21 }
- 看到这宏定义有点折磨, 无从下手, 想起来一个好东西
gcc -E
, 嘿嘿, 这下人肉展开是不可能的, 直接安排
ubuntu@VM-12-14-ubuntu:~/ics/ics2020/nemu$ gcc -E ./src/isa/x86/reg.c
# 1 "./src/isa/x86/reg.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 31 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 32 "<command-line>" 2
# 1 "./src/isa/x86/reg.c"
./src/isa/x86/reg.c:1:10: fatal error: isa.h: No such file or directory
1 | #include <isa.h>
| ^~~~~~~
compilation terminated.
- 啊这, 我又麻了, 果然没有这么简单, 单独
gcc -E
是不行了, 依赖的文件都得加上才行, 可是这个脚本命令有点不会写啊, 来cat一下jyy的Makefile
// -E 我们都懂的, 可是-MF是什么,google一下,这里我是废物, 我又被google到的中文结果吸引进去了
(CC) $(CFLAGS) -E -MF /dev/null $< | \
@$-ve '^#' | \
grep -format - > $(basename $@).i clang
gcc -MF $< - 看完之后我又行了, 不就是建立个文件夹, 然后把每个.c
的文件都预编译成.i
文件, 我又拿捏了, 走着
-12-14-ubuntu:~/ics/ics2020/nemu$ make -B
ubuntu@VM
-nemu-interpreter
Building x86+ CC src/device/audio.c
/bin/sh: 3: clang-format: Permission denied
: *** [Makefile:81: build/obj-x86-interpreter/device/audio.o] Error 127 make
- 啊这,啊这. 怎么直接都无法编译了, 定睛一看,
Permission denied
, 这我熟, 直接掏出祖传sudo
sudo make -B
-12-14-ubuntu:~/ics/ics2020/nemu$ sudo make -B
ubuntu@VM
-nemu-interpreter
Building x86+ CC src/device/audio.c
/bin/sh: 3: clang-format: not found
: *** [Makefile:81: build/obj-x86-interpreter/device/audio.o] Error 127 make
- 通往pa1完成的道路上充满了坎坷, 说到底还是太菜了, 好在linux的报错信息太perfect了,
clang-format: not found
, easy, 这种小问题还是可以的直接sudo apt-get install clang-format
-12-14-ubuntu:~/ics/ics2020/nemu$ sudo apt-get install clang-format
ubuntu@VM
... Done
Reading package lists
Building dependency tree ... Done
Reading state information:
The following NEW packages will be installed-format
clang0 upgraded, 1 newly installed, 0 to remove and 251 not upgraded.
0 B/3,272 B of archives.
Need to get , 29.7 kB of additional disk space will be used.
After this operation-format.
Selecting previously unselected package clang(Reading database ... 143254 files and directories currently installed.)
.../clang-format_1%3a10.0-50~exp1_amd64.deb ...
Preparing to unpack -format (1:10.0-50~exp1) ...
Unpacking clang-format (1:10.0-50~exp1) ...
Setting up clangfor man-db (2.9.1-1) ... Processing triggers
- 冲冲冲…
- sudo make -B
- 又看到了熟悉的命令行信息+cc…, 奶思情况好转起来了
- 直接冲到
reg.i
里面看看到底是个啥情况
// 找到reg.i
(fzf) vim $
reg.i
1
2
3 typedef unsigned char __u_char;
4 typedef unsigned short int __u_short;
5 typedef unsigned int __u_int;
6 typedef unsigned long int __u_long;
...
46 typedef long int __clock_t;
47 typedef unsigned long int __rlim_t;
48 typedef unsigned long int __rlim64_t;
49 typedef unsigned int __id_t;
50 typedef long int __time_t;
- 诶,窝草,怎么满屏的定义, 不慌不慌, 直接搜索函数
reg_test
, 嘿嘿好起来了.又看到了熟悉的代码
2066 const char *regsl[] = {"eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"};
2067 const char *regsw[] = {"ax", "cx", "dx", "bx", "sp", "bp", "si", "di"};
2068 const char *regsb[] = {"al", "cl", "dl", "bl", "ah", "ch", "dh", "bh"};
2069
2070 void reg_test() {
2071 srand(time(0));
2072 word_t sample[8];
2073 word_t pc_sample = rand();
2074 cpu.pc = pc_sample;
2075
2076 int i;
2077 for (i = R_EAX; i <= R_EDI; i++) {
2078 sample[i] = rand();
2079 (cpu.gpr[check_reg_index(i)]._32) = sample[i];
2080
2081 ((void)sizeof(
2082 ((cpu.gpr[check_reg_index(i)]._16) == (sample[i] & 0xffff)) ? 1 : 0),
2083 __extension__({
2084 if ((cpu.gpr[check_reg_index(i)]._16) == (sample[i] & 0xffff))
2085 ;
2086 else
2087 __assert_fail("reg_w(i) == (sample[i] & 0xffff)", "src/isa/x86/reg.c",
2088 20, __extension__ __PRETTY_FUNCTION__);
2089 }));
2090 }
我擦, 我在搞什么飞机, 胡乱分析系统, 好家伙, jyy老师直接给出了ans. 强行分析一波. 唉, 这波说明在操作前看README的重要性. - 好家伙, 我是真的服了我了,没有困难制造困难,代码就这么几行,我愣是没看到,只需要重新修改下就行, 我还在苦思冥想该怎么写, 怎么老是测试不过, 原来贴心的jyy老是早就猜到了我的水平,让我改改代码就完事了,大意了。
x86.h
修改如下
typedef struct
{
union{
union {
uint32_t _32;
uint16_t _16;
uint8_t _8[2];
} gpr[8];
struct{
, ecx, edx, ebx, esp, ebp, esi, edi;
rtlreg_t eax};
};
;
vaddr_t pc} x86_CPU_state;
- 接着冲冲冲
- make -B -j8
- oh oh oh oh oh….
运行第一个客户程序
单步执行:
- si [N]
- 让程序单步执行, 这里有个小bug,不过也不算小bug,需要打开调试的宏
DEBUG
在common.h
中, 否则无法查看单步执行后的几寄存器的效果
ui.c
static int cmd_si(char *args) {
// strtok is split string with specify symbol
// strtok(args,"")
int step;
if(args == NULL) step=1;
// format string and move to a new vable
else sscanf(args,"%d",&step);
// excute num
(step);
cpu_execreturn 0;
}
ui.c
> cmd_table
{ "si", "Debug by step NEMU", cmd_si },
- 这个单步调试很关键哦, 后续的内存扫描需要用到这里作为校验,刚开始自己直接忽略了,吃了大亏,出来混还是的还的。
> ### 打印程序(寄存器)状态 > - 就是打印寄存器中的数据 > - 仿照上面的案例,修改
cmd_table
, 建立cmd_info
函数
这里调用了reg.c
中的isa_reg_display
记得导入头文件
#include "memory/vaddr.h"
void isa_reg_display() {
for (int i = R_EAX; i < R_EDI; i++)
{
("$%s\t0x%08x\n", regsl[i] ,reg_l(i));
printf}
("$pc\t0x%08x\n",cpu.pc);
printf}
ui.c
static int cmd_info(char* args){
// show register
if (args[0] == 'r') isa_reg_display();
// show watch pointer
else if(args[0] == 'w') TODO();
return 0;
}
ui.c
> cmd_table
{ "info", "info r-->show reg\ninfo w-->show watch pointer memory", cmd_info },
- 注意这里的
info
是使用的info r
进行测试,后面的info w
暂时先搁置,先搞后面的扫描内存>### 扫描内存(2)
- 这里可有点弯弯绕,我最初的想法是通过传递进来的地址,然后直接按照16进制数进行数据的解析,好家伙, 我想的是真复杂了(好吧,我承认我又没有认真看手册,手册里面都说了,前面我们都看了内存是怎么设计的。。。。),
vaddr_read
害。。
- 还是熟悉的套路:
ui.c
> cmd_table
{ "x", "show memory from 0xxxx", cmd_x }
ui.c
- 第一个参数是扫描的长度, 第二个参数是起始位置
static int cmd_x(char* args){
uint32_t len;
uint32_t addr;
char* N = strtok(NULL," ");
char* EXPR = strtok(NULL," ");
(N,"%d",&len);
sscanf(EXPR,"%x",&addr);
sscanf
for(int i=addr;i<addr+(len*4);i+=4){
= vaddr_read(i,4);
word_t value ("$0x%08x:\t0x%08x\n", i,value);
printf}
return 0;
}
- 测试:
gdb中文参考:https://wizardforcel.gitbooks.io/100-gdb-tips/content/examine-memory.html
表达式求值
- 正则表达式
expr.h
&expr.c
- 正则表达式的C语言使用
正则表达式在线测试: https://c.runoob.com/front-end/854/
正则表达式代码参考地址: https://www.ibm.com/docs/en/i/7.4?topic=functions-regcomp-compile-regular-expression - 正则表达式的基本使用 regcomp()
#include <regex.h>
int regcomp(regex_t *preg, const char *pattern, int cflags);
regexec()
参考链接: https://blog.csdn.net/weixin_46499713/article/details/125154268 https://blog.csdn.net/weixin_43877657/article/details/109068930?spm=1001.2014.3001.5502